/*
 * Tabela.java
 *
 * Created on 7 de Maio de 2007, 10:29
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package org.jerm.Mapeamento.Tabelas;

import java.util.ArrayList;

import org.jerm.Mapeamento.Atributos.Atributo;
import org.jerm.Mapeamento.Atributos.AtributoSerial;
import org.jerm.Mapeamento.Atributos.FK;

/**
 * Classe do Mapeamento de uma Tabela
 * @author Tiago Falcao
 * @version Ideterminada
 */
public class Tabela {
    /**
     * Nome da Tabela
     */
    protected String Nome;
    /**
     * Vetor com Todos Atributo nao Estrangeiros que participam da chave
     */
    protected ArrayList<Atributo> Chave;          //Vetor com nome dos atributos primos nao FK
    /**
     * Vetor com Todos Atributo Estrangeiros que participam da chave
     */
    protected ArrayList<FK> ChaveFKs;             //Vetor com os atributos FK participantes da Chave
    /**
     * Vetor com Todos Atributo Estrangeiros que nao participam da chave
     */
    protected ArrayList<FK> FKs;                  //Vetor com os atributos FK
    /**
     * Vetor com Todos Atributo nao Estrangeiros que nao participam da chave
     */
    protected ArrayList<Atributo> Atributos;      //Todos Atributos da Tabela n�o listado em outras listas
    /**
     * Vetor com Todos Indices da Tabela(Conjuntos de Atributos)
     */
    protected ArrayList<Indice> Indices;                    //Vetor com os Indices da Tabela ( a fazer)
    /**
     * Vetor com Todos Indices Unicos da Tabela(Conjuntos de Atributos)
     */
    protected ArrayList<Indice> Unicos;                      //Vetor com os Unicos da Tabela ( a fazer)
    
    protected ArrayList<String> NomeAtributos;
    
    /**
     * Cria nova instancia de Tabela
     * @param Nome Nome da Tabela
     */
    public Tabela(String Nome)
    {
        this.Nome=Nome;
        this.Chave=new ArrayList();
        this.ChaveFKs=new ArrayList();
        this.Atributos=new ArrayList();
        this.FKs=new ArrayList();
        this.Indices=new ArrayList();
        this.NomeAtributos=new ArrayList();
    }
    
    /**
     * Cria nova instancia de Tabela sem Nome
     */
    public Tabela()
    {
        this.Nome=new String();
        this.Chave=new ArrayList();
        this.ChaveFKs=new ArrayList();
        this.Atributos=new ArrayList();
        this.FKs=new ArrayList();
        this.Indices=new ArrayList();
        this.NomeAtributos=new ArrayList();
    }
    
    /**
     * Determina Nome da Tabela
     * @param Nome Nome da Tabela
     */
    public void setNome(String Nome)
    
    {
        this.Nome=Nome;
    }
    
    /**
     * Retorna Nome da Tabela
     * @return String Nome da Tabela
     */
    public String getNome()
    {
        return Nome;
    }
    
    /**
     * Retorna Noma Formatado para SQL
     * @return String com Nome para SQL
     * @param SGBD Nome do SGBD alvo
     */
    public String getNomeSQL(String SGBD)
    {
        return Nome;
    }
    
    /**
     * Adiciona Atributo
     * @param Atributo Atributo a ser Adicionado
     * @return Boolean terminante do sucesso da Operacao
     */
    public boolean addAtributo(Atributo Atributo)
    {
        if(NomeAtributos.contains(Atributo.getNome())){
            System.out.println("Ja Existe um "+Atributo.getNome()+" na Tabela "+Nome);
            return false;
        }
        NomeAtributos.add(Atributo.getNome());
        Atributos.add(Atributo);
        return true;
    }
    
    /**
     * Adiciona Atributo Primo
     * @param Primo Atributo Primo a ser Adicionado
     * @return Boolean terminante do sucesso da Operacao
     */
    public boolean addPrimo(Atributo Atributo)
    {
        if(NomeAtributos.contains(Atributo.getNome())){
            System.out.println("Ja Existe um "+Atributo.getNome()+" na Tabela "+Nome);
            return false;
        }
        NomeAtributos.add(Atributo.getNome());
        Chave.add(Atributo);
        return true;
    }
    
    /**
     * Adiciona Atributo Estrangeiro Primo
     * @param FK Atributo Estrangeiro Primo a ser Adicionado
     * @return Boolean terminante do sucesso da Operacao
     */
    public boolean addFKPrimo(FK Atributo)
    {
        if(NomeAtributos.contains(Atributo.getNome())){
            System.out.println("Ja Existe um "+Atributo.getNome()+" na Tabela "+Nome);
            return false;
        }
        NomeAtributos.add(Atributo.getNome());
        ChaveFKs.add(Atributo);
        return true;
    }
    
    /**
     * Adiciona Atributo Estrangeiro
     * @param FK Atributo Estrangeiro a ser Adicionado
     * @return Boolean terminante do sucesso da Operacao
     */
    public boolean addFK(FK Atributo)
    {
        if(NomeAtributos.contains(Atributo.getNome())){
            System.out.println("Ja Existe um "+Atributo.getNome()+" na Tabela "+Nome);
            return false;
        }
        NomeAtributos.add(Atributo.getNome());
        FKs.add(Atributo);
        return true;
    }
    
    /**
     * Adiciona Atributo Estrangeiro Primo
     * @param FK Atributo Estrangeiro Primo a ser Adicionado
     * @return Boolean terminante do sucesso da Operacao
     */
    public boolean addFKPrimo(Tabela Tabela, AtributoSerial Atributo)
    {
        String nome="fkk"+Integer.toString(getSizeFKPrimo())+"_"+Atributo.getNome();
        FK fk=new FK();
        fk.setNome(nome);
        try {
            fk.setReferencia(Tabela,Atributo);
        } catch (Exception ex) {
            System.out.println("Erro na Criacao do Atributo FK Primo");
            return false;
        }
        ChaveFKs.add(fk);
        return true;
    }
    
    /**
     * Adiciona Atributo Estrangeiro
     * @param FK Atributo Estrangeiro a ser Adicionado
     * @return Boolean terminante do sucesso da Operacao
     */
    public boolean addFK(Tabela Tabela, AtributoSerial Atributo)
    {
        String nome="fkk"+Integer.toString(getSizeFK())+"_"+Atributo.getNome();
        FK fk=new FK();
        fk.setNome(nome);
        try {
            fk.setReferencia(Tabela,Atributo);
        } catch (Exception ex) {
            System.out.println("Erro na Criacao do Atributo FK");
            return false;
        }
        FKs.add(fk);
        return true;
    }
    
    public int getSizeFK(){
        return FKs.size();
    }
    
    public int getSizeFKPrimo(){
        return ChaveFKs.size();
    }
    
    public Object[] getFKPrimo(){
        return ChaveFKs.toArray();
    }
    public Object[] getFK(){
        return FKs.toArray();
    }
    
    public Object[] getChave(){
        ArrayList a=new ArrayList();
        a.addAll(Chave);
        a.addAll(ChaveFKs);
        return a.toArray();
    }
    
    public Object[] getPrimo(){
        return Chave.toArray();
    }
    public Object[] getAtributo(){
        return Atributos.toArray();
    }
    
    
    /**
     * Retorna String com Mapeamento Logico da Tabela
     * @return String Mapeamento Logico
     */
    public String getMER(){
        String Retorno;
        int i;
        int count=0;
        
        Retorno=this.getNome()+"(";
        
        i=this.Chave.size()-1;
        while(i>=0)
        {
            if(count>0)
                Retorno+=",";
            Retorno+="_"+this.Chave.get(i).getNome();
            i--;
            count++;
        }
        
        
        i=this.ChaveFKs.size()-1;
        while(i>=0)
        {
            if(count>0)
                Retorno+=",";
            Retorno+="_*"+this.ChaveFKs.get(i).getNome();
            i--;
            count++;
        }
        
        
        
        i=this.Atributos.size()-1;
        while(i>=0)
        {
            if(count>0)
                Retorno+=",";
            Retorno+=this.Atributos.get(i).getNome();
            i--;
            count++;
        }
        
        
        i=this.FKs.size()-1;
        while(i>=0)
        {
            if(count>0)
                Retorno+=",";
            Retorno+="*"+this.FKs.get(i).getNome();
            i--;
            count++;
        }
        
        
         Retorno+=")\n";
        
        return Retorno;
    }
    
    /**
     * Retorna Codigo SQL para criacao da Tabela em SGBD Generico
     * @return String Codigo SQL para criacao da Tabela
     * @throws java.lang.Exception Caso a Tabela nao possua Nome
     */
    public String getSQL() throws Exception{
        return this.getSQL("SQL");
    }
    
    /*
     *CREATE TABLE `swlanguagephrases` (
`phraseid` int(10) unsigned NOT NULL auto_increment,
`languageid` int(10) unsigned NOT NULL default '0',
`section` varchar(100) collate latin1_general_ci NOT NULL default '',
`code` varchar(100) collate latin1_general_ci NOT NULL default '',
`sectioncode` varchar(255) collate latin1_general_ci NOT NULL default '',
`contents` text collate latin1_general_ci NOT NULL,
PRIMARY KEY (`phraseid`),
UNIQUE KEY `languageid` (`languageid`,`code`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci AUTO_INCREMENT=1161 ;*/
    
    
    
    
    /**
     * Retorna Codigo SQL para criacao da Tabela em SGBD Determinado
     * @return String Codigo SQL para criacao da Tabela
     * @throws java.lang.Exception Caso a Tabela nao possua Nome
     * @param SGBD Nome do SGBD alvo
     */
    public String getSQL(String SGBD) throws Exception{
        String Retorno;
        int i;
        
        Retorno="CREATE TABLE "+this.getNome()+"{\n";
        
        i=this.Chave.size()-1;
        while(i>=0)
        {
            Retorno+=this.Chave.get(i).getSQL(SGBD)+"\n";
            i--;
        }
        
        
        i=this.ChaveFKs.size()-1;
        while(i>=0)
        {
            Retorno+=this.ChaveFKs.get(i).getSQL(SGBD)+"\n";
            i--;
        }
        
        
        i=this.Atributos.size()-1;
        while(i>=0)
        {
            Retorno+=this.Atributos.get(i).getSQL(SGBD)+"\n";
            i--;
        }
        
        
        i=this.FKs.size()-1;
        while(i>=0)
        {
            Retorno+=this.FKs.get(i).getSQL(SGBD)+"\n";
            i--;
        }
        
        
        i=this.ChaveFKs.size()-1;
        while(i>=0)
        {
            Retorno+=this.ChaveFKs.get(i).getFKSQL(SGBD)+"\n";
            i--;
        }
        
        i=this.FKs.size()-1;
        while(i>=0)
        {
            Retorno+=this.FKs.get(i).getFKSQL(SGBD)+"\n";
            i--;
        }
        
        
        /////////////////////////////////////////////////
        
        
        i=this.Chave.size()-1;
        int j=this.ChaveFKs.size();
        
        if(i>=0 || j>0)
            Retorno+="PRIMARY KEY(";
        
        while(i>0)
        {
            Retorno+=this.Chave.get(i).getNome()+",";
            i--;
        }
        
        if(i==0){
            Retorno+=this.Chave.get(i).getNome();
            if(j==0)
                Retorno+=")\n";
            else
                Retorno+=",";
        }
            
        j--;
        while(j>0)
        {
            Retorno+=this.ChaveFKs.get(j).getNome()+",";
            j--;
        }
        
        if(j==0)
            Retorno+=this.ChaveFKs.get(j).getNome()+")\n";
        
        
        Retorno+="};\n";
        return Retorno;
        
    }
    
}
